import Singlelon from '../Common/Singlelon';
import { BundleConfig } from '../NeedChange/BundleConfig';
const { ccclass, property } = cc._decorator;

@ccclass
export default class ResMgr extends Singlelon<ResMgr>() {

    //用于管理包，加载包，获取包;获取资源
    //存储管理各种资源的管理器
    private _mapBundle: Map<string, cc.AssetManager.Bundle> = new Map();

    //加载资源包
    async loadBundle(bundleName: string): Promise<cc.AssetManager.Bundle> {
        return new Promise((resovle, reject) => {
            if (bundleName.length <= 0 || !bundleName) {
                return;
            }
            let path = BundleConfig[bundleName].path;
            cc.assetManager.loadBundle(path, (err: Error, bundle: cc.AssetManager.Bundle) => {
                if (err) {
                    cc.error(path + "包加载出错");
                    return;
                }
                //包加载完成，就将这个包存储到包容器中
                this._mapBundle.set(bundleName, bundle);
                //为了实现同步，将资源加载完成后存入到resovle中，后面的语句才会执行
                resovle(bundle);
            })
        });
    }

    //获取包
    getBundle(bundleName) {
        // let bundle = this._mapBundle.get(bundleName);
        // if (!bundle) {
        //     this.loadBundle(bundleName);
        // }
        return this._mapBundle.get(bundleName);
    }
    //加载资源
    async loadRes<T extends cc.Asset>(bundleName: string, resName: string): Promise<T> {
        if (bundleName.length <= 0 || !bundleName || resName.length <= 0 || !resName) {
            return;
        }
        //先获取包
        let bundle = this.getBundle(bundleName);
        if (!bundle) {
            //如果资源包没有存储，就加载资源包并且存储
            await this.loadBundle(bundleName);
            bundle = this.getBundle(bundleName);
            if (!bundle) {
                cc.error(bundleName + "包加载失败");
                return;
            }
        }

        return new Promise((resovle, reject) => {
            // 根据resourceType加载特定类型的资源
            bundle.load(resName, (err, asset) => {
                if (err) {
                    cc.error(`加载资源 ${resName} 失败:`, err);
                    reject(err);
                    return;
                }
                resovle(asset as T);
            })
        })
    }

    async loadAtlasRes(bundleName: string, resName: string): Promise<cc.SpriteAtlas> {
        if (bundleName.length <= 0 || !bundleName || resName.length <= 0 || !resName) {
            return;
        }
        //先获取包
        let bundle = this.getBundle(bundleName);
        if (!bundle) {
            //如果资源包没有存储，就加载资源包并且存储
            await this.loadBundle(bundleName);
            bundle = this.getBundle(bundleName);
            if (!bundle) {
                cc.error(bundleName + "包加载失败");
                return;
            }
        }

        return new Promise((resovle, reject) => {
            // 明确指定加载类型为cc.SpriteAtlas
            bundle.load(resName, cc.SpriteAtlas, (err, asset) => {
                if (err) {
                    cc.error(`加载图集资源失败`);
                    return;
                }
                resovle(asset as cc.SpriteAtlas);
            })
        })
    }

    //获取资源,获取的是已经加载过的资源
    getRes<T extends cc.Asset>(bundleName: string, resName: string): T {
        if (bundleName.length <= 0 || !bundleName || resName.length <= 0 || !resName) {
            return null;
        }
        //先获取包
        let bundle = this.getBundle(bundleName);
        if (!bundle) {
            cc.error(bundleName + "包不存在");
            return null;
        }
        //获取资源
        let res = bundle.get(resName);
        if (!res) {
            return null;
        }
        return <T>res;
    }
    //按需加载资源，这些资源是没有加载过的，需要加载后放入到对应的包中
    async getResWithNeed<T>(bundleName: string, resName: string): Promise<T> {
        if (bundleName.length <= 0 || !bundleName || resName.length <= 0 || !resName) {
            return;
        }
        //先获取包
        let bundle = this.getBundle(bundleName);
        if (!bundle) {
            cc.error(bundleName + "包不存在");
            return null;
        }
        return new Promise((resovle, reject) => {

            bundle.load(resName, (err, asset) => {
                if (err) {
                    return null;
                }
                resovle(<T>asset);
            })
        })
    }
}


